﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Browser;
using GraphDrawer.GraphProvider;
using System.Windows.Threading;
using GRender;
using System.IO;
using prefuse.action.layout.graph;
using GraphLayout.Interface;
using GraphLayout.GraphRepresentation;

namespace GraphDrawer
{
    public partial class Page : UserControl
    {
        private GraphViewer _v;
        public String graphML;
        public String model;
        private DispatcherTimer _timer;
        GraphProvider.GraphProviderServiceSoapClient cl;
        //TODO: set it to session  ID
        String token = "12";
        bool isNextStep = false;
        bool isContinous = false;
        int simNumber = 0;
        string creationType;
        GraphDrawer.GraphProvider.Graph generatedGraph;

        public Page(String pgraphML, String pmodel)
        {
            graphML = pgraphML;
            model = pmodel;
            InitializeComponent();
            this.Background = new SolidColorBrush(Colors.Black);
            //GraphProvider.GraphProviderServiceClient c = new GraphDrawer.GraphProvider.GraphProviderServiceClient();
			creationType = "graphml";
        }

		public Page(GraphDrawer.GraphProvider.Graph g, String pmodel) {
			generatedGraph = g;
			model = pmodel;
			InitializeComponent();
			this.Background = new SolidColorBrush(Colors.Black);
			creationType = "generator";
		}

        public void Page_Loaded(object o, EventArgs e)
        {
            // Required to initialize variables
            InitializeComponent();

			switch (creationType) {
				case "graphml":
					try
					{
						cl = new GraphProviderServiceSoapClient();
						cl.GetAvailableMethodsOfCentralityCompleted += new EventHandler<GetAvailableMethodsOfCentralityCompletedEventArgs>(cl_GetAvailableMethodsOfCentralityCompleted);
						cl.CreateGraphCompleted += new EventHandler<CreateGraphCompletedEventArgs>(cl_CreateGraphCompleted);
						cl.NextStepCompleted += new EventHandler<NextStepCompletedEventArgs>(cl_NextStepCompleted);
						cl.GetAvailableMethodsOfGeneratorAsync();
						cl.GetAvailableMethodsOfGeneratorAsync();
						cl.CreateGraphAsync(graphML, model, token, 100);
						//cl.GetGraphCompleted+=new EventHandler<GetGraphCompletedEventArgs>(cl_GetGraphCompleted);
						//cl.GetGraphAsync();
					}
					catch (Exception ex)
					{
						this.Details.Text = "Error while loading graph: " + ex.Message + ". \n Loading a random graph instead.";
					}
					break;
				case "generator":
                    cl = new GraphProviderServiceSoapClient();
                    cl.GetAvailableMethodsOfCentralityCompleted += new EventHandler<GetAvailableMethodsOfCentralityCompletedEventArgs>(cl_GetAvailableMethodsOfCentralityCompleted);
                    cl.CreateGraphCompleted += new EventHandler<CreateGraphCompletedEventArgs>(cl_CreateGraphCompleted);
                    cl.NextStepCompleted += new EventHandler<NextStepCompletedEventArgs>(cl_NextStepCompleted);
                    cl.GetAvailableMethodsOfGeneratorAsync();
                    cl.GetAvailableMethodsOfGeneratorAsync();
                    showGraph(generatedGraph);
					break;
				default:
					break;
            }
        }

        void cl_GetAvailableMethodsOfCentralityCompleted(object sender, GetAvailableMethodsOfCentralityCompletedEventArgs e)
        {
            foreach (var item in e.Result)
            {
                Centrality.Items.Add(item);
            }
            Centrality.SelectedIndex = 0;
        }

		void cl_CreateGraphCompleted(object sender, CreateGraphCompletedEventArgs e)
        {
            try
            {
                GraphDrawer.GraphProvider.Graph g = e.Result;
                this.Details.Text = "";
                this.Title.Text = "";                

                _timer = new DispatcherTimer()
                {
                    Interval = new TimeSpan(0, 0, 0, 0, 100)
                };

                _timer.Tick += new EventHandler(_timer_Tick);

                simNumber++;
                this.SimulationNumber.Text = simNumber.ToString();

                /* Execute the spiffy graph visualizer */
                _v = new GraphViewer(g, new Size(780, 600), _timer);
                _v.DoLayout();

                /* Add the result to the current screen */
                this.MainCanvas.Children.Insert(0, _v.Canvas);
                this.MainCanvas.Height = _v.Canvas.Height;
                this.MainCanvas.Width = _v.Canvas.Width;
                this.MainCanvas.HorizontalAlignment = HorizontalAlignment.Center;


                _timer.Start();

            }
            catch (Exception ex)
            {
                this.Details.Text += ex.ToString();
            }
        }

        void showGraph(GraphDrawer.GraphProvider.Graph g)
        {
            try
            {
                this.Details.Text = "";
                this.Title.Text = "";

                _timer = new DispatcherTimer()
                {
                    Interval = new TimeSpan(0, 0, 0, 0, 100)
                };

                _timer.Tick += new EventHandler(_timer_Tick);

                simNumber++;
                this.SimulationNumber.Text = simNumber.ToString();

                /* Execute the spiffy graph visualizer */
                _v = new GraphViewer(g, new Size(780, 600), _timer);
                _v.DoLayout();

                /* Add the result to the current screen */
                this.MainCanvas.Children.Insert(0, _v.Canvas);
                this.MainCanvas.Height = _v.Canvas.Height;
                this.MainCanvas.Width = _v.Canvas.Width;
                this.MainCanvas.HorizontalAlignment = HorizontalAlignment.Center;


                _timer.Start();

            }
            catch (Exception ex)
            {
                this.Details.Text += ex.ToString();
            }
        }

        void cl_NextStepCompleted(object sender, NextStepCompletedEventArgs e)
        {
            foreach (KeyValuePair<GraphElement, NodeState> item in _v._nodeState)
            {
                TextBlock nodeStateTitle = null;
                foreach (var control in item.Value.NodeCanvas.Children)
                {
                    if (control is TextBlock)
                    {
                        nodeStateTitle = (TextBlock)control;
                        break;
                    }
                }

                foreach (var element in e.Result.Vertices)
                {
                    if (item.Key.Id == element.Id)
                    {
                        if (nodeStateTitle != null && !_v.isDetailView)
                        {
                            foreach (var description in element.Keys)
                            {
                                if (description.Key == GraphViewer.LabelToDisplay)
                                {
                                    nodeStateTitle.Text = description.Value;
                                    break;
                                }
                            }
                        }

                        item.Key.Keys = element.Keys;
                        item.Key.Height = element.Height;
                        item.Key.Width = element.Width;
                        item.Key.x = element.x;
                        item.Key.y = element.y;
                        break;
                    }
                }
            }
            if (isContinous)
            {
                isNextStep = !isNextStep;
            }
            else
            {
                this.NextStep.IsEnabled = true;
            }
            _v.StepLayout();
            simNumber++;
            this.SimulationNumber.Text = simNumber.ToString();
            
        }

        void _timer_Tick(object sender, EventArgs e)
        {
            //_v.StepLayout();
            //if (isContinous && !isNextStep)
            //{
            //    cl.NextStepAsync(token);
            //    isNextStep = !isNextStep;
            //}

            _v.StepLayout();

            if (simNumber == 10)
            {
                isNextStep = false;
                isContinous = false;
                simNumber = 0;
                _timer.Stop();
            }

            if (isContinous && !isNextStep)
            {
                cl.NextStepAsync(token);
                isNextStep = !isNextStep;
            }

        }

        void cl_GetGraphCompleted(object sender, GraphDrawer.GraphProvider.CreateGraphCompletedEventArgs e)
        {
            try
            {
                GraphDrawer.GraphProvider.Graph g = e.Result;                
                //TODO: set title adn text
                this.Details.Text = "";
                this.Title.Text = "";

                _timer = new DispatcherTimer()
                {
                    Interval = new TimeSpan(0, 0, 0, 0, 100)
                };

                _timer.Tick += new EventHandler(_timer_Tick);



                /* Execute the spiffy graph visualizer */
                _v = new GraphViewer(g, new Size(780, 600), _timer);
                _v.DoLayout();

                /* Add the result to the current screen */
                this.MainCanvas.Children.Insert(0, _v.Canvas);
                this.MainCanvas.Height = _v.Canvas.Height;
                this.MainCanvas.Width = _v.Canvas.Width;
                this.MainCanvas.HorizontalAlignment = HorizontalAlignment.Center;


                _timer.Start();

            }
            catch (Exception ex)
            {
                this.Details.Text += ex.ToString();
            }
        }

        private void NextStep_Button_Click(object sender, RoutedEventArgs e)
        {
            this.NextStep.IsEnabled = false;
            cl.NextStepAsync(token);
        }

        private void Run_Button_Click(object sender, RoutedEventArgs e)
        {
            if (!isContinous)
            {
                this.Run.Content = "Stop";
                isContinous = true;
                isNextStep = false;
                this.NextStep.IsEnabled = false;
            }
            else
            {
                this.Run.Content = "Run";
                isContinous = false;
                this.NextStep.IsEnabled = true;
            }
        }

        private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

        }
    }
}
